package com.zengfa.task.server.application.impl;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSONObject;
import com.zengfa.task.api.enums.JobStatus;
import com.zengfa.task.api.enums.JobType;
import com.zengfa.task.api.model.JobDTO;
import com.zengfa.task.api.model.JobNodeDTO;
import com.zengfa.task.api.service.ServerApiService;
import com.zengfa.task.api.utils.JobUtil;
import com.zengfa.task.server.application.JobAppService;
import com.zengfa.task.server.dao.JobDao;
import com.zengfa.task.server.dao.JobNodeDao;
import com.zengfa.task.server.domain.entity.Job;
import com.zengfa.task.server.domain.entity.JobNode;
import com.zengfa.task.server.domain.service.IJobNodeService;
import com.zengfa.task.server.domain.service.IJobService;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class JobAppServiceImpl implements JobAppService{

//	@Autowired
//	private IJobService jobService;
//	@Autowired
//	private IJobNodeService jobNodeService;
//	@Autowired
//	private Environment environment;
	@Autowired
	private JobDao jobDao;
	@Autowired
	private JobNodeDao jobNodeDao;
	
	@Override
	public JobDTO getJob(String jobId) {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public void stopJob(String jobId) {
		Job job = jobDao.getById(jobId);
		stopJob(job);
	}
	
	@Override
	public void stopJob(Job job) {
		job.setStatus(JobStatus.STOP);
		job.setUpdateTime(LocalDateTime.now());
		job.setEndTime(LocalDateTime.now());
		jobDao.updateById(job);
		List<JobNode> list = jobNodeDao.listByJobId(job.getJobId());
		if (CollectionUtils.isEmpty(list)) {
			return;
		}
		for(JobNode r : list) {
			JobStatus status = r.getStatus();
			if(JobStatus.RUNNING != status) {
				continue;
			}
			r.setStatus(JobStatus.STOP);
			r.setUpdateTime(LocalDateTime.now());
			r.setEndTime(LocalDateTime.now());
			jobNodeDao.updateById(r);
		}
	}
	
	@Override
	public List<JobNode> getJobNodeList(String bizType, String bizId) {
		List<JobNode> list = new ArrayList<>();
		Job job = jobDao.findJob(bizType, bizId);
		if(null != job){
			list = jobNodeDao.listByJobId(job.getJobId());
		}
		return list;
	}
	@Override
	public JobNodeDTO retryJobNode(String nodeId) {
		// TODO Auto-generated method stub
		return null;
	}
	
	/**
	 * 检测心跳
	 */
	@Scheduled(cron="0/5 * * * * ? ")
	public void checkHeartbeat() {
		log.debug("checkHeartbeat");
		ThreadPoolTaskExecutor executor = JobUtil.getTaskExecutor("syncJob");
		List<Job> jobList = jobDao.listByStatus(JobStatus.RUNNING);
		for(Job job : jobList) {
			executor.execute(() -> {
				LocalDateTime lastSyncTime = job.getLastSyncTime();
				boolean checkSyncTimeRes = checkSyncTimeExpire(lastSyncTime);
				//判断心跳是否过期
				if(checkSyncTimeRes) {
					job.setStatus(JobStatus.ERROR);
					job.setMessage("超时失败");
					jobDao.updateByIdAndStatus(job, JobStatus.RUNNING);
				}
				/*
				boolean lockSuccess = jobDao.lock(job.getJobId());
				if(lockSuccess) {
					log.info("加锁成功:"+job.getJobId());
					try {
						clientApiSupport.syncJobStatus(job);
						updJobSyncTime(job);
					}finally {
						jobDao.unLock(job.getJobId());
						log.info("释放锁:"+job.getJobId());
					}
				} else {
					LocalDateTime lastSyncTime = job.getLastSyncTime();
					boolean checkSyncTimeRes = checkSyncTimeExpire(lastSyncTime);
					if(checkSyncTimeRes) {
						jobDao.unLock(job.getJobId());
					}
				}
				*/
			});
		}
	}
	
	/**
	 * 判断同步时间是否过期，最后同步时间超过10分钟后可以特殊处理
	 * @param lastSyncTime
	 * @return	false:没过期,true过期
	 */
	private boolean checkSyncTimeExpire(LocalDateTime lastSyncTime) {
		if(lastSyncTime == null) {
			return false;
		}
		int i = lastSyncTime.plusMinutes(10L).compareTo(LocalDateTime.now());
		if (i > 0) {
			return false;
		}
		return true;
	}
	
}
